// import { Component } from "react";
// import React from 'react';
// import ReactDOM from 'react-dom';

import VisualBase from "./VisualBase";
import './Visual.css';
import Table2DHelper from "./Table2DHelper";

import {Table2DHtmlString, Table2DMathString, Table2DString} from './Table2DItem';
// 表格元素
class Table2DDomElement {
  
  constructor(width=200, height=200, rows=2, cols=3){
    var domElement     = document.createElement('table');
    var headDomElement = document.createElement('thead');
    var bodyDomElement = document.createElement('tbody');
    var footDomElement = document.createElement('tfoot');

    domElement.appendChild(headDomElement);
    domElement.appendChild(bodyDomElement);
    domElement.appendChild(footDomElement);

    this.headDomElement = headDomElement;
    this.bodyDomElement = bodyDomElement;
    this.footDomElement = footDomElement;

    this.width  = width;
    this.height = height;

    domElement.style.border = '1px solid black';
    domElement.style.backgroundColor = '#FFFFFF';

    this.domElement     = domElement;
    this.init(rows, cols);

    this.update();
  }

  // 初始化
  init(rows, cols){
    var defaultStyle = {
      'bgColor'     : '#FFFFFF' ,
      'highLightColor' : '#00FF00',
      'borderTop'   : 1         , 
      'borderBottom': 1         , 
      'borderLeft'  : 1         , 
      'borderRight' : 1         , 
      'borderStyle' : 'solid'   , 
      'borderColor' : '#000000' ,
      'textAlign'   : 'center'  ,
      'verticalAlign': 'middle' ,
    };
    this.defaultStyle = defaultStyle;

    this.rowDomElements = [];

    for(var i = 0; i <= rows; i++){
      const newRow = new Table2DRowDomElement(cols);
      if( i === 0){
        newRow.hidden = true;
      }
      this.rowDomElements.push(newRow);
    }

    // 单元格样式
    this.cellStyles = [];
    for(var r = 0; r <= rows; r++){
      this.cellStyles.push([]);
      for(var c = 0; c <= cols; c++){
        this.cellStyles[r].push(defaultStyle);
      }
    }

    this.rowCount = parseInt(rows);
    this.colCount = parseInt(cols);

    // console.log(this.rowCount, this.colCount);
  }
  // 重新设置大小
  resize(rows, cols){
    this.init(rows, cols);
    this.update();
  }

  // 设置宽高
  setSize(w, h){
    this.width = w;
    this.height = h;
  }

  insertRow(row){
    row = parseInt(row);
    const rows = this.rows();
    const cols = this.cols();
    const newRow = new Table2DRowDomElement(cols);
    let c = 0;
    if(row <= 0){
      this.rowDomElements.splice(1,0,newRow);
      this.cellStyles.splice(1,0,[]);
      for(c = 0; c <= cols; c++){
        this.cellStyles[1].push(this.defaultStyle);
      }
    }
    else if(row >= rows){
      this.rowDomElements.push(newRow);
      this.cellStyles.push([]);
      for(c = 0; c <= cols; c++){
        this.cellStyles[rows + 1].push(this.defaultStyle);
      }
    }
    else {
      this.rowDomElements.splice(row + 1, 0,newRow);
      this.cellStyles.splice(row + 1, 0,[]);
      for(c = 0; c <= cols; c++){
        this.cellStyles[row + 1].push(this.defaultStyle);
      }
    }
    this.rowCount += 1;
    this.update();
  }

  insertCol(col){
    col = parseInt(col);
    const rows = this.rows();
    const cols = this.cols();
    for(var r = 0; r <= rows; r++){
      this.getRow(r).insertCell(col);
      if(col <= 0){
        this.cellStyles[r].splice(1, 0, this.defaultStyle);
      }
      else if(col >= cols){
        this.cellStyles[r].push(this.defaultStyle);
      }
      else{
        this.cellStyles[r].splice(col + 1, 0, this.defaultStyle);
      }
    }
    this.colCount += 1;
    this.update();
  }

  // 获取单元格Dom El
  cell(row, col){
    // console.log(row, col, this.rowDomElements[row].cellDomElements[col]);
    return this.rowDomElements[row].cellDomElements[col].domElement;
  }
  // 获取单元格
  getCell(row, col){
    return this.rowDomElements[row].cellDomElements[col];
  }
  // 获取行
  getRow(row){
    return this.rowDomElements[row];
  }
  // 获取行数
  rows(){
    return this.rowCount;
  }
  // 获取列数
  cols(){
    return this.colCount;
  }
  // 合并单元格
  mergeCells(row, col, rowSpan, colSpan){
    row = parseInt(row);
    col = parseInt(col);
    rowSpan = parseInt(rowSpan);
    colSpan = parseInt(colSpan);
    if(row <= 0 || row > this.rows()) return;
    if(col <= 0 || col > this.getRow(row).cols()) return;

    if(row + rowSpan > this.rows() + 1) return;
    if(col + colSpan > this.cols() + 1) return;

    if(rowSpan <= 0) rowSpan = this.rows() - row;
    if(colSpan <= 0) colSpan = this.getRow(row).cols() - col;

    // 如果有隐藏的单元格返回
    for(let r = row; r < row + rowSpan; r++){
      for(let c = col; c < col + colSpan; c++){
        if(this.getCell(r, c).hidden) return;
      }
    }

    // 恢复原合并
    this.restoreCells(row, col);
    // 合并单元格
    const cell = this.getCell(row, col);
    cell.rowSpan = `${rowSpan}`;
    cell.colSpan = `${colSpan}`;

    for(let r = row; r < row + rowSpan; r++){
      for(let c = col; c < col + colSpan; c++){
        if(r === row && c === col) continue;
        this.getCell(r, c).hidden = true;
      }
    }
    this.update();
  }
  // 恢复合并的单元格
  restoreCells(row, col){
    if(row <= 0 || row > this.rows()) return;
    if(col <= 0 || col > this.getRow(row).cols()) return;
    const cell = this.getCell(row, col);
    
    var rowSpan = parseInt(cell.rowSpan);
    var colSpan = parseInt(cell.colSpan);
    if(rowSpan === 0) rowSpan = this.rows() - row;
    if(colSpan === 0) colSpan = this.getRow(row).cols() - col;

    if(rowSpan === 1 && colSpan === 1) return;

    for(var r = row ; r < row + rowSpan; r++){
      for(var c = col ; c < col + colSpan; c++){
        this.getCell(r, c).hidden = false;
      }
    }
  }

  // 设置单元格样式
  setStyle(row, col, style){
    if(row === 0 && col === 0){
      this.cellStyles[row][col] = style;
    }
    else if(row !== 0 && row < this.rows() && col === 0){
      for(var c = 1; c < this.getRow(row).cols(); c++){
        this.cellStyles[row][c] = style;
      }
    }
    else if(col !== 0 && row === 0){
      for(var r = 1; r < this.rows(); r++){
        if(col < this.getRow(r).cols()){
          this.cellStyles[r][col] = style;
        }        
      }
    }
    else {
      if(row < this.rows()){
        if(col < this.getRow(row).cols()){
          this.cellStyles[row][col] = style;
        }
      }       
    }
  }

  getStyle(row, col){
    if(row === 0 && col === 0){
      return this.cellStyles[row][col];
    }
    else if(row !== 0 && row < this.rows() && col === 0){
      return this.cellStyles[row][1];
    }
    else if(col !== 0 && row === 0){
      return this.cellStyles[1][col];
    }
    else {
      return this.cellStyles[row][col];
    }
  }

  updateStyle(style){
    let domElement = this.domElement;

    domElement.style.borderTop       = `${style.borderTop}px`;
    domElement.style.borderBottom    = `${style.borderBottom}px`;
    domElement.style.borderLeft      = `${style.borderLeft}px`;
    domElement.style.borderRight     = `${style.borderRight}px`;

    domElement.style.borderStyle     = style.borderStyle;
    domElement.style.borderColor     = style.borderColor;

    domElement.style.backgroundColor = style.bgColor;
  }

  update(){

    let domElement = this.domElement;

    while(domElement.hasChildNodes()){
      domElement.removeChild(this.domElement.lastChild);
    }

    // 0:0 为表格样式
    this.updateStyle(this.cellStyles[0][0]);

    domElement.style.width  = `${this.width}px`;
    domElement.style.height = `${this.height}px`;

    domElement.style.overflow = 'auto';

    for(var r = 1; r <= this.rows(); r++){
      const row = this.getRow(r);
      for(var c = 1; c < row.cols(); c++){
        this.getCell(r, c).style = this.cellStyles[r][c];
      }
    }

    for(var i = 0, il = this.rowDomElements.length; i < il; i++){      
      if(!this.rowDomElements[i].hidden){
        this.rowDomElements[i].update();
        this.domElement.appendChild(this.rowDomElements[i].domElement);
      }      
    }
  }
}
// 行
class Table2DRowDomElement {
  constructor(cols=3){
    var domElement  = document.createElement('tr');
    this.domElement = domElement;

    this.cellDomElements      = [];
    this.init(cols);
    this.style = {};
    this.update();
  }

  cell(col){
    return this.cellDomElements[col];
  }

  cols(){
    return this.cellDomElements.length;
  }

  init(cols){
    for(var i = 0; i <= cols; i++){
      const newCell = new Table2DCellDomElement();
      newCell.hidden = (i === 0);
      this.cellDomElements.push(newCell);
    }
  }

  insertCell(index){
    index = parseInt(index);
    const newCell = new Table2DCellDomElement();
    if(index <= 0){
      this.cellDomElements.splice(1,0,newCell);
    }
    else if(index >= this.cols()){
      this.cellDomElements.push(newCell);
    }
    else {
      this.cellDomElements.splice(index + 1,0,newCell);
    }
  }

  removeAllCells(){
    this.cellDomElements = [];
  }

  update(){
    while(this.domElement.hasChildNodes()){
      this.domElement.removeChild(this.domElement.lastChild);
    }

    for(var i = 0, il = this.cellDomElements.length; i < il; i++){
      if(!this.cellDomElements[i].hidden){
        this.cellDomElements[i].update();
        this.domElement.appendChild(this.cellDomElements[i].domElement);
      }
    }
  }
}
// 单元格
class Table2DCellDomElement {
  constructor(){
    var domElement = document.createElement('th');

    this.hidden  = false;
    this.isSelected = false;
    this.rowSpan = '1';
    this.colSpan = '1';
    this.domElement = domElement;

    this.init();
    
    this.style   = {};
    this.update();
  }

  init(){
    this.domElement.rowSpan = this.rowSpan;
    this.domElement.colSpan = this.colSpan;
    this.domElement.style.borderTop = '1px';
    this.domElement.style.borderStyle = 'solid';
    this.domElement.style.borderColor = 'red';

    // this.domElement.style.minWidth = '120px';
    // this.domElement.style.minHeight = '850px';
  }

  updateStyle(){
    const style = this.style;
    const domElement = this.domElement;

    domElement.style.borderTop       = `${style.borderTop}px`;
    domElement.style.borderBottom    = `${style.borderBottom}px`;
    domElement.style.borderLeft      = `${style.borderLeft}px`;
    domElement.style.borderRight     = `${style.borderRight}px`;

    domElement.style.borderStyle     = style.borderStyle;
    domElement.style.borderColor     = style.borderColor;

    domElement.style.textAlign       = style.textAlign;
    domElement.style.verticalAlign   = style.verticalAlign;

    domElement.style.backgroundColor = this.isSelected?style.highLightColor:style.bgColor;
  }

  update(){
    this.updateStyle();

    this.domElement.rowSpan = this.rowSpan;
    this.domElement.colSpan = this.colSpan;

    this.domElement.innerHTML='';
  };
}
// 2D表格
class Table2D extends VisualBase{
  constructor(width=200, height=200, rows=5, cols=5, bgColor='#FFFFFF'){
    super('Table2D');

    const domElement = this.domElement;

    this.helper = <Table2DHelper visual={this}/>;

    var table    = document.createElement('div'); 
    table.style.display         = 'flex';
    table.style.justifyContent  = 'center';
    table.style.backgroundColor = bgColor;
    table.style.padding         = '5px';

    const tableDomElement = new Table2DDomElement(width, height, rows, cols);
    table.appendChild(tableDomElement.domElement);

    domElement.appendChild(table);
    this.tableDomElement = tableDomElement;
    this.table           = table;

    // this.tableDomElements = [[]];
    // this.tableStyles      = [[]];

    this.addAttribute('width'        , width    , 'number' , '外观');
    this.addAttribute('height'        , height    , 'number' , '外观');
    this.addAttribute('rows'        , rows    , 'number' , '外观');
    this.addAttribute('cols'        , cols    , 'number' , '外观');
    this.addEvent('插入行', this.insertRow.bind(this), '外观');
    this.addEvent('插入列', this.insertCol.bind(this), '外观');
    this.addAttribute('fitToWindow' , true    , 'boolean', '外观');

    this.addAttribute('bgColor'        , bgColor  , 'color', '通用');  
    this.addAttribute('highLightColor' , '#00FF00', 'color', '通用');  

    this.init();

    // this.resizeTable(rows, cols);

    this.initInput();

    this.needUpdate = false;
  }

  insertRow(){
    const row = parseInt(this.row);
    this.tableDomElement.insertRow(row);
    this.rows = this.tableDomElement.rows();
  }

  insertCol(){
    const col = parseInt(this.col);
    this.tableDomElement.insertCol(col);
    this.cols = this.tableDomElement.cols();
  }

  init(){
    // 边框
    this.addAttribute('borderTop'   , 1         , 'number'    , '边框');
    this.addAttribute('borderBottom', 1         , 'number'    , '边框');
    this.addAttribute('borderLeft'  , 1         , 'number'    , '边框');
    this.addAttribute('borderRight' , 1         , 'number'    , '边框');
    this.addAttribute('borderStyle' , 'solid'   , 'lineStyle' , '边框')
    this.addAttribute('borderColor' , '#000000' , 'color'     , '边框');

    // 文本
    this.addAttribute('textAlign'       , 'center'  , 'textAlign'     , '文本');
    this.addAttribute('verticalAlign'   , 'middle'  , 'verticalAlign' , '文本');

    // 单元格
    this.addAttribute('row' , 0, 'number', '单元格');
    this.addAttribute('col' , 0, 'number', '单元格');
    this.addAttribute('rowSpan' , 1, 'number', '单元格');
    this.addAttribute('colSpan' , 1, 'number', '单元格');
    this.addEvent('合并单元格', this.mergeCells.bind(this), '单元格');
    // this.addEvent('拆分单元格', this.spliteCell.bind(this), '单元格');
    // 尺寸
  }

  mergeCells(){
    const row = this.row;
    const col = this.col;
    const rowSpan = this.rowSpan;
    const colSpan = this.colSpan;

    this.tableDomElement.mergeCells(row, col, rowSpan, colSpan);
  }

  // spliteCell(){

  // }


  updateStyle(){
    const row = this.row;
    const col = this.col;
    var style = {};
    style['borderTop']   = this.borderTop;
    style['borderBottom']= this.borderBottom;
    style['borderLeft']  = this.borderLeft;
    style['borderRight'] = this.borderRight;
    style['borderStyle'] = this.borderStyle;
    style['borderColor'] = this.borderColor;
    style['textAlign']   = this.textAlign;
    style['verticalAlign'] = this.verticalAlign;
    style['bgColor']     = this.bgColor;
    style['highLightColor'] = this.highLightColor;

    // this.tableDomElement.cellStyles[row][col] = style;
    this.tableDomElement.setSize(this.width, this.height);
    this.tableDomElement.setStyle(row, col, style);
  }

  // updateTable(){
  //   // remove all child
  //   while(this.table.hasChildNodes()){
  //     this.table.removeChild(this.table.lastChild);
  //   }

  //   // this.tableDomElement.domElement.style.display = 'table';
  //   this.tableDomElement.domElement.style.flex    = this.fitToWindow?1:'';
  //   this.updateStyle();
  //   this.tableDomElement.update();
  //   this.table.appendChild(this.tableDomElement.domElement);
  // }

  clearAll(){
    this.items = [];
    this.update();
  }

  clear(){
    const rows = this.tableDomElement.rows();
    const cols = this.tableDomElement.cols();

    if(cols !== parseInt (this.cols) || rows !== parseInt (this.rows)){
      this.tableDomElement.resize(this.rows, this.cols);
    }

    // remove all child
    while(this.table.hasChildNodes()){
      this.table.removeChild(this.table.lastChild);
    }

    // this.tableDomElement.domElement.style.display = 'table';
    this.tableDomElement.domElement.style.flex    = this.fitToWindow?1:'';
    this.updateStyle();
    this.tableDomElement.update();
    this.table.appendChild(this.tableDomElement.domElement);

  }
  //////////////////////////////////////// 添加成员 ////////////////////////////
  addString(str, row, col){
    const newString = new Table2DString(str, row, col);
    this.items.push(newString);
    return newString.uuid;
  }

  addMathString(str, row, col){
    const newMathString = new Table2DMathString(str, row, col);
    this.items.push(newMathString);
    return newMathString.uuid;
  }

  addHtmlString(str, row, col){
    const newHtmlString = new Table2DHtmlString(str, row, col);
    this.items.push(newHtmlString);
    return newHtmlString.uuid;
  }

  renderItems(){
    // console.log('...', this.tableDomElement);
    for(var i=0, il= this.items.length; i < il; i++){
      this.items[i].render(this.tableDomElement);
    }
  }

  update(){
    this.clear();
    // this.updateTable();

    this.renderItems();
    this.updateHelper();
  }

  getCellIndex(x, y){
    
    var offsetTop = this.tableDomElement.domElement.offsetTop - window.scrollY;
    var offsetLeft = this.tableDomElement.domElement.offsetLeft - window.scrollX;
    var height  = this.tableDomElement.domElement.clientHeight;
    var width   = this.tableDomElement.domElement.clientWidth;
    if( y < offsetTop || y > offsetTop + height ) return [0, 0];
    if( x < offsetLeft || x > offsetLeft + width) return [0, 0];

    for(var r = 1; r <= this.tableDomElement.rows(); r++){
      // const row = this.tableDomElement.getRow(r);
      for(var c = 1; c <= this.tableDomElement.cols(); c++){
        const dom = this.tableDomElement.cell(r, c);
        const cellTop    = dom.offsetTop + offsetTop;
        const cellLeft   = dom.offsetLeft + offsetLeft;
        const cellBottom = dom.clientHeight + cellTop;
        const cellRight  = dom.clientWidth + cellLeft;
        if( y >= cellTop && y <= cellBottom && x >= cellLeft && x <= cellRight){
          return [r, c];
        }
      }
    }

    return [0, 0];
  }

  onMouseDown(event){

    const x = parseInt(event.x);
    const y = parseInt(event.y);
    const offsetTop = this.tableDomElement.domElement.offsetTop - window.scrollY;
    const offsetLeft = this.tableDomElement.domElement.offsetLeft - window.scrollX;
    const height  = this.tableDomElement.domElement.clientHeight;
    const width   = this.tableDomElement.domElement.clientWidth;
    if( x < offsetLeft || x > offsetLeft + width ) return;
    if( y < offsetTop || y > offsetTop + height) return;

    const cell = this.getCellIndex(x, y);
    if(this.row && this.col){
      this.tableDomElement.getCell(this.row, this.col).isSelected = false;
    }
    if(this.row === cell[0] && this.col === cell[1]){
      this.row = 0;
      this.col = 0;
      this.tableDomElement.getCell(cell[0], cell[1]).isSelected = false;
    }
    else {
      this.row = cell[0];
      this.col = cell[1];
      this.tableDomElement.getCell(cell[0], cell[1]).isSelected = true;      
    }
    this.tableDomElement.update();
    this.renderItems();
    // this.needUpdate = true;
  }
}

function showMathStringInTable(dom, dat, transpose=false){
  if(!dom) return;
  
  let table = new Table2D();
  dom.appendChild(table.domElement);

  if(!transpose){
    table.rows = dat.length;
    table.cols = dat[0].length;
    for(let r = 1, rl = dat.length; r <= rl; r++){
      for(let c = 1, cl = dat[r-1].length; c <= cl; c++){
        table.addMathString(dat[r-1][c-1], r, c);
      }
    }
  }
  else{
    table.rows = dat[0].length;
    table.cols = dat.length;
    for(let r = 1, rl = dat.length; r <= rl; r++){
      for(let c = 1, cl = dat[r-1].length; c <= cl; c++){
        table.addMathString(dat[r-1][c-1], c, r);
      }
    }
  }

  table.update();
}

export default Table2D;
export {showMathStringInTable};